
/**
 *
 */
package com.et114.modules.org.services;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;


import net.sf.ehcache.CacheException;

import com.et114.components.acegi.AcegiContext;
import com.et114.components.acegi.Constants;
import com.et114.components.acegi.cache.AcegiCacheManager;
import com.et114.components.tree.tree51.BaseTree51Model;
import com.et114.components.xmlparse.XMLUtils;
import com.et114.core.common.CONST;
import com.et114.core.exception.CheckException;
import com.et114.core.services.impl.BaseServicesImpl;
import com.et114.core.utility.GetterUtil;
import com.et114.core.utility.NumberUtils;
import com.et114.core.utility.StringPool;
import com.et114.modules.org.action.FuncAction;
import com.et114.modules.org.dao.FunctionAttachDAO;
import com.et114.modules.org.dao.FunctionCompDAO;
import com.et114.modules.org.dao.FunctionDAO;
import com.et114.modules.org.dao.GroupDao;
import com.et114.modules.org.dao.RoleDAO;
import com.et114.modules.org.dao.TitleDAO;
import com.et114.modules.org.message.FuncMessageManager;
import com.et114.modules.org.utility.MenuUtils;
import com.et114.modules.org.utility.tree.OrgGroupTree;
import com.et114.modules.org.vo.AclVo;
import com.et114.modules.org.vo.FuncComponentVo;
import com.et114.modules.org.vo.FuncRoleRelVo;
import com.et114.modules.org.vo.FunctionAttachVo;
import com.et114.modules.org.vo.FunctionVo;
import com.et114.modules.org.vo.RoleVo;
import com.et114.modules.org.vo.TitleMsgVo;
import com.et114.modules.org.vo.UserEmplyVo;
import com.et114.modules.org.vo.UserVo;


  
/**
 * Auth :: Authority
 * @author guanhw
 */
public class FunctionManager extends BaseServicesImpl implements InitializingBean{
	private FunctionDAO  functionDAO ;
	private FunctionCompDAO functionCompDAO ;
	private FunctionAttachDAO functionAttachDAO ;
	private RoleDAO roleDAO ;
	private TitleDAO titleDAO ;
	private GroupDao groupDao ;
	private int mSpil = 30 ;

	public static String pathSplit = ">>" ;

	public void afterPropertiesSet ( ) throws Exception {
		// TODO Auto-generated method stub
	}

	public void setTitleDAO ( TitleDAO titleDAO ) {
		this.titleDAO = titleDAO;
	}
	public void setRoleDAO ( RoleDAO roleDAO ) {
		this.roleDAO = roleDAO;
	}
	public void setFunctionDAO ( FunctionDAO functionDAO ) {
		this.functionDAO = functionDAO;
	}
	public void setFunctionCompDAO ( FunctionCompDAO functionCompDAO ) {
		this.functionCompDAO = functionCompDAO;
	}
	public void setFunctionAttachDAO ( FunctionAttachDAO functionAttachDAO ) {
		this.functionAttachDAO = functionAttachDAO;
	}
	public void setGroupDao( GroupDao groupDao ) {
        this.groupDao = groupDao;
    }
	//
	public int getmSpil ( ) {
		return mSpil;
	}
	public void setmSpil ( int mSpil ) {
		if ( mSpil >= 25 ) this.mSpil = mSpil;
	}

	/***************************************************************************************
	 *      getUsersAndPrincipals                     菜单维护
	 */
	public List getFuncsWithPrincipals() throws CheckException {
		List funcs = functionDAO.getFuncs() ;
		for  ( int  i = 0 ; i <  funcs.size() ; i ++  ) {
			FunctionVo func = ( FunctionVo ) funcs.get(  i ) ;
			if ( func.getResString ( )  != null && func.isLeaf ( )  ) {
				List roles = getRolesByFunc ( func ) ;
				List titles = getTitlesByFunc( func ) ;
				for ( java.util.Iterator iter = titles.iterator ( ) ; iter.hasNext ( ) ; ) {
					TitleMsgVo title = ( TitleMsgVo ) iter.next ( );
					List titleRoles = titleDAO.getRolesByTitle ( title );
					roles.addAll ( titleRoles );
				}
				List users = getUsersByFunc( func ) ;
				func.setRoles( roles ) ;
				func.setTitles( titles ) ;
				func.setUsers( users ) ;
			}
		}
		return funcs ;
	}

	public void modifyInCache( FunctionVo func  ) throws CheckException , CacheException {
		if ( !func.isLeaf ( ) ) return;
		List roles = getRolesByFunc( func ) ;
		List titles = getTitlesByFunc( func ) ;
		for ( java.util.Iterator iter = titles.iterator ( ) ; iter.hasNext ( ) ; ) {
			TitleMsgVo title = ( TitleMsgVo ) iter.next ( );
			List titleRoles = titleDAO.getRolesByTitle ( title );
			roles.addAll ( titleRoles );
		}		
		List users = getUsersByFunc( func ) ;
		func.setRoles( roles ) ;
		func.setTitles( titles ) ;
		func.setUsers( users ) ;
		AcegiCacheManager.getInstansce ( ).modifyResourceInCache ( func ) ;
	}

	public List loadFunctionsByIds ( String[] funcIds ) throws CheckException { 
		return functionDAO.loadFunctionsByIds ( funcIds ) ; 
	}

	/**
	 * 0 : node 1 : leaf
	 */
	public synchronized void addFunc( FunctionVo function ) throws Exception{
		Long pi = function.getFfuncId ( );
		String path = "" ; 
		//操作符节点
		if ( !NumberUtils.isEmptyOrZero ( pi )   ) { // add sub
			FunctionVo pf = getFunc ( pi ) ;
			String resString = pf.getSecureUrl ( ) ;
			path = pf.getPath ( ) + StringPool.SLE + path ;
			if ( pf.isLeaf ( ) ) {  // leaf
				// update
				pf.setLeaf ( false ) ;
				pf.setSecureUrl ( "/" ) ;
				pf.setUrl ( "/" ) ;
				//删除子功能
				List funcComps  = getFuncCompsByFuncId ( pf.getFuncId ( ) );
				for ( java.util.Iterator iter = funcComps.iterator ( ) ; iter.hasNext ( ) ;  ) {
					FuncComponentVo fcv = ( FuncComponentVo )  iter.next ( );
					deleteFuncComp ( fcv.getFuncElementId ( ) , function.getOperUser ( ) ) ;
				}
				//删除附件信息
				deleteFuncAttachsByFuncId ( pf.getFuncId ( ) ,  function.getOperUser ( )  ) ;

				updateFunc( pf ) ;
				AcegiCacheManager.getInstansce ( ).removeResourceFromCache ( resString ) ;
			}
		}
		function.setSecureUrl ( function.getUrl ( ) ) ;
		Long funcId = functionDAO.addFunc ( function ) ;	
		AcegiCacheManager.getInstansce ( ).resourceDetailsNullAuthorityInCache (
				function.getSecureUrl ( ) , Constants.RESOURCE_URL );

		//
		function.setPath ( path + funcId ) ;
		long funcNo = funcId.longValue ( ) ;
		if ( !NumberUtils.isEmptyOrZero ( pi )  )    {
			int piCount = countFuncsByPid ( pi ) ;
			if ( piCount == 1  ) { funcNo = pi.longValue ( ) * mSpil + piCount   ;  }
			else  { funcNo = functionDAO.maxFuncNoByParentId( pi ) .longValue ( ) + 1;  }
		}
			
		else funcNo =+ ( funcNo * mSpil ) ;
		
		function.setFuncNo ( new Long ( funcNo ) ) ; 
		functionDAO.updateFunc ( function ) ; 
	}

	/////////////////////////////////////////
	/**
	 * 0 : node 1 : leaf
	 */
	
	public synchronized void updateFunc( FunctionVo function ) throws CheckException , CacheException {
		Long funcId = function.getFuncId ( );
		if ( function.getFfuncId ( ) != null  && function.getFfuncId ( ).longValue ( ) == 0 )
			function.setFfuncId (  null  ) ;
		// 检查换父节点

		// 检查url
		String url = function.getUrl ( );
		FunctionVo oldFunc = getFunc ( funcId ) ;
		String secureUrl = oldFunc.getSecureUrl ( ) ;
		String oldUrl = oldFunc.getUrl ( ) ;
		if ( !oldUrl .equals ( url ) &&  function.isLeaf ( ) ) {
			//更新缓存
			if ( secureUrl != null  ) {
				StringBuffer sb = new StringBuffer();
				StringTokenizer sts = new StringTokenizer( secureUrl , StringPool.SEMICOLON ) ;
				int count = sts.countTokens ( ) ;
				for (  int i = 0 ; i  < count ; i ++ ) {
					String st = sts.nextToken ( ) ;
					if ( i == 0  ) sb.append ( url ) ;
					else sb.append ( st ) ;
					if ( count - 1 != i  ) sb.append ( StringPool.SEMICOLON )  ;
				}
				function.setSecureUrl ( sb.toString ( ) ) ;
			}
			else 
				function.setSecureUrl ( url  ) ;
			
			functionDAO.updateFunc ( function  ) ;
			//since 1.72
			if ( secureUrl == null
					|| Constants.NULL_URL.equals ( secureUrl )
					|| AcegiCacheManager.getInstansce ( ).getAuthorityFromCache ( secureUrl ) == null ) {
				modifyInCache ( function );
				AcegiCacheManager.getInstansce ( ).removeResourceFromCache( secureUrl ) ;
				logger.warn ( "ALLWAYS:WARN>> cache warn !"  ) ; 
			}
			else 
				AcegiCacheManager.getInstansce ( ).putAuthorityInCacheByByOther ( secureUrl ,
								function.getSecureUrl ( ) , true );
		}
		else {
			functionDAO.updateFunc ( function  ) ;
		}
	}




	public synchronized void deleteFunc( Long id  , Long operUser ) throws CheckException , CacheException {
		FunctionVo fv = getFunc ( id ) ;
		fv.setOperUser ( operUser ) ;
		deleteFunc ( fv ) ;
		//delete acl

		//delete cache

		//delete 功能
		List funcComps  = getFuncCompsByFuncId ( fv.getFuncId ( ) );
		for ( java.util.Iterator iter = funcComps.iterator ( ) ; iter.hasNext ( ) ;  ) {
			FuncComponentVo fcv = ( FuncComponentVo )  iter.next ( );
			deleteFuncComp ( fcv.getFuncElementId ( ) , operUser ) ;
			//delete acl
			//delete cache
		}


		//attach
		deleteFuncAttachsByFuncId ( id , operUser ) ;
	}


	private void deleteFunc( FunctionVo function ) throws CheckException , CacheException{
		Long pid = function.getFfuncId ( );
		if ( pid != null &&  pid.longValue ( ) != 0  ) {
			int countFuncs = countFuncsByPid( pid ) ;
			if ( countFuncs == 1 ) {
				FunctionVo pfvo = getFunc ( pid ) ;
				pfvo.setLeaf ( true ) ;
				updateFunc ( pfvo ) ;
			}
		}

		functionDAO.deleteFuncById ( function.getFuncId ( ) , function.getOperUser ( ) ) ;

		//
		FuncRoleRelVo funcRoleRel = new FuncRoleRelVo(  ) ;
		funcRoleRel.setFuncId ( function.getFuncId ( ) ) ; 
		functionDAO.deleteFuncRoleRel ( funcRoleRel ) ;
		
		//delete acl
		OrgFactory.getAclManager ( ).deleteAclByFuncId ( function.getFuncId ( ) , function.getOperUser ( )) ;

		//delete cache
        AcegiCacheManager.getInstansce ( ).removeResourceFromCache (  function.getResString ( ) ) ;
	}





	/**
	 *
	 * @param function
	 * @return
	 * @throws CheckException
	 */
	public List getFuncs( FunctionVo function ) throws CheckException {
		return functionDAO.getFuncs ( function ) ;
	}

	
	public List getFunctionsWithCountRel( FunctionVo  vo  ) throws CheckException {  	
		return functionDAO.getFunctionsWithCountRel ( vo ) ;
	}
	
	public List getRoots () throws CheckException {
		return functionDAO.getRoots ( ) ;
	}

	public List getRootsWithCountRel( ) throws CheckException { 
		return functionDAO.getRootsWithCountRel ( ) ; 
	}
	
	public List getChilds( Long pid ) throws CheckException {
		FunctionVo vo = new FunctionVo();
		vo.setFfuncId ( pid  ) ;
		return functionDAO.getFuncs ( vo ) ;
	}
	
	public List getChildsWithCountRel( Long pid  )  throws CheckException {
		FunctionVo vo = new FunctionVo();
		vo.setFfuncId ( pid  ) ;
		return functionDAO.getFunctionsWithCountRel ( vo ) ; 
	}


	public FunctionVo getFunc( Long id )  throws CheckException {
		return functionDAO.getFunc ( id ) ;
	}


	public int countFuncsByPid ( Long pid )  throws CheckException {
		FunctionVo vo = new FunctionVo();
		vo.setFfuncId ( pid ) ;
		return functionDAO.countFuncs ( vo ) ;
	}



	public List getRolesByFunc( FunctionVo vo ) throws CheckException {
		return  functionDAO.getRolesByFunc( vo ) ;
	}
	
	public List getGreaterRolesByFunction ( FunctionVo  vo ,  byte page ) throws CheckException {  
		if( page == CONST.PAGE )  return functionDAO.getGreaterRolesByFunction( vo ) ;
		return functionDAO.getGreaterRolesByFunctionNPage ( vo ) ;
	}
	
	public Long countgetGreaterRolesByFunction ( FunctionVo  vo ) throws CheckException {
		return  functionDAO.countgetGreaterRolesByFunction( vo ) ;
	}

	public List getTitlesByFunc( FunctionVo vo ) throws CheckException {
		return  functionDAO.getTitlesByFunc (  vo ) ;
	}

	public Long countgetTitlesByFunction( FunctionVo  vo  ) throws CheckException {  
		return functionDAO.countgetTitlesByFunction ( vo ) ; 
	}
	
	public List getUsersByFunc( FunctionVo vo ) throws CheckException {
		List us = functionDAO.getUsersByFunc (  vo ) ;
		for ( Iterator iter = us.iterator(); iter.hasNext(); ) {
			UserVo user = ( UserVo ) iter.next ( ) ;
            UserEmplyVo uev = OrgFactory.getGroupManager ( ).loadEmpByUser(user.getUserId());
			user.setUserEmplyVo ( uev ) ;
		}
		return  us ;
	}

	/****************************************************************************************
	 *
                  生成功能树
	 */


	public  String generateFuncTreeStr ( BaseTree51Model tree51Model ) throws CheckException {
		StringBuffer sb = new StringBuffer ( );
		String funcRootUrlAction = tree51Model.getRootHref ( ) != null ? tree51Model.getRootHref ( ) : null ;
		String funcRootText = tree51Model.getBaseName ( ) != null ? tree51Model.getBaseName ( ) : null ;
		String funcTargetAction = tree51Model.getHref ( ) != null ? tree51Model.getHref ( ) : null ;
		String funcSubUrlAction = tree51Model.getSrc ( ) != null ? tree51Model.getSrc ( ) : null ;
		boolean isLeaf = !tree51Model.isRoot ( ) ;
		String path = tree51Model.getLocValue ( ) != null ? tree51Model.getLocValue ( ) : null ; 
		List list = tree51Model.getChildNodes ( ) != null ? tree51Model.getChildNodes ( ) : new ArrayList ( ) ;
		if ( ! isLeaf ) { //TODO  改grpId ： nodeId
			sb.append ( "<gyj:tree pic='root' nodeId=\"-1\"   "
					+ "  text=\"" + funcRootText + "\"" );	
			if ( funcRootUrlAction != null && list != null && list.size ( ) > 0   ) sb.append ( " href=" ).append ( "\"" +   funcRootUrlAction + "\" "  ) ;			
			if ( tree51Model.getTarget ( ) != null ) sb.append ( " target=" ).append ( "\"" +   tree51Model.getTarget ( ) + "\" "  ) ;			
			if ( path != null ) sb.append ( " locvalue=" ).append ( "\"" +  path  + "\" "  ) ;
			if ( tree51Model.getIsTarget ( ) != null ) sb.append ( " isTarget=" ).append ( "\"" +  tree51Model.getIsTarget ( )  + "\" "  ) ;
			if ( tree51Model.getTxtOnclick ( ) != null ) sb.append ( " txtonclick=" ).append ( "\"" +  tree51Model.getTxtOnclick ( )  + "\" "  ) ;
			sb.append ( " >\n" ) ;	
		}
		for ( int i = 0 ; i < list.size ( ) ; i ++ ) {
			FunctionVo node = ( FunctionVo ) list.get ( i );
			Long id = node.getFuncId ( ) ;
			String name = node.getFuncChn ( );
			boolean leaf = node.isLeaf ( );
			if ( leaf )// 叶子
				sb.append ( "    <gyj:tree href=\"" + funcTargetAction + "funcId="
						+ id + "\" " + "text=\"" + name
						+ "\"  " );

			else if ( ! leaf ) {
				sb.append ( "    <gyj:tree src=\"" + funcSubUrlAction + "&funcId="
						+ id + "\"" + " href=\"" + funcTargetAction + "funcId="
						+ id + "\" " + "   text=\""
						+ name + "\" " );
			}
			if ( tree51Model.getTarget ( ) != null ) sb.append ( " target=" ).append ( "\"" +   tree51Model.getTarget ( ) + "\" "  ) ;
		    sb.append ( " nodeId=" ).append ( "\"" +  id  + "\" "  ) ;
			if ( tree51Model.getOnclick ( ) != null ) sb.append ( " onclick=" ).append ( "\"" +  tree51Model.getOnclick ( ) + "\" "   ) ;
			if ( tree51Model.getOndbClick ( ) != null ) sb.append ( " ondblclick=" ).append ( "\"" + tree51Model.getOndbClick ( ) + "\" " ) ;
			if ( tree51Model.getTxtOnclick ( ) != null ) sb.append ( " txtonclick=" ).append ( "\"" +  tree51Model.getTxtOnclick ( )  + "\" "  ) ;
		    sb.append ( " />\n" ) ;			
		}
		if ( ! isLeaf ) sb.append ( "</gyj:tree>\n" );
		return sb.toString ( );
	}	
	
	
	public String generateGroupTreeStr (   boolean isLeaf , List list ,
			String locValue , String isTarget , java.util.Locale locale , Long funcId  )
			throws CheckException {
		GroupManager gm  = OrgFactory.getGroupManager ( ) ;
    	OrgGroupTree orgGroupTree = new OrgGroupTree( ) ; 
    	orgGroupTree.setBaseName ( FuncMessageManager.get ( locale ).getMessage ( "group.tree.root" ) ) ;
    	orgGroupTree.setSrc ( "func.go?method=loadChildGroups&second=y&funcId=" + funcId + "&" ) ; 
    	orgGroupTree.setHref ( "func.go?method=loadAuths&second=y&_m=title&funcId=" + funcId + "&" ) ;
    	orgGroupTree.setRoot ( !isLeaf ) ;
    	orgGroupTree.setTarget ( "frmRight" ) ; 
    	orgGroupTree.setChildNodes (  list ) ;
    	orgGroupTree.setIsTarget ( BaseTree51Model.IS_TARGET_Y ) ; 
    	if ( locValue != null )
    		orgGroupTree.setLocValue ( locValue ) ; 
    	orgGroupTree.setOnclick ( "initTree51Node( this )" ) ; 
    	return gm.generateGroupTreeStr( orgGroupTree ) ;
	}		
	
	public String generateGroupTreeStr (   boolean isLeaf , List list ,
			String locValue , String isTarget , java.util.Locale locale , Long funcId , Long funcCompId )
			throws CheckException {
		StringBuffer sb = new StringBuffer () ; 
		sb.append ( "&second=y&funcId=" ).append ( funcId ).append ( "&funcElementId=" )
				.append ( funcCompId ).append ( "&" );
		GroupManager gm  = OrgFactory.getGroupManager ( ) ;
    	OrgGroupTree orgGroupTree = new OrgGroupTree( ) ; 
    	orgGroupTree.setBaseName ( FuncMessageManager.get ( locale ).getMessage ( "group.tree.root" ) ) ;
    	orgGroupTree.setSrc ( "funcComp.go?method=loadChildGroups" + sb.toString ( ) ) ; 
    	orgGroupTree.setHref ( "funcComp.go?method=loadAuths&_m=title"  + sb.toString ( ) ) ;
    	orgGroupTree.setRoot ( !isLeaf ) ;
    	orgGroupTree.setTarget ( "frmRight" ) ; 
    	orgGroupTree.setChildNodes (  list ) ;
    	orgGroupTree.setIsTarget ( BaseTree51Model.IS_TARGET_Y ) ; 
    	if ( locValue != null )
    		orgGroupTree.setLocValue ( locValue ) ; 
    	orgGroupTree.setOnclick ( "initTree51Node( this )" ) ; 
    	return gm.generateGroupTreeStr( orgGroupTree ) ;
	}			
	
	 /**********************************************************************************************
	  *     菜单授权
	  */

	/**
	 * principalIds 角色字符 1;2;3;4;5 角色授权
	 * setRoleType 设置role类型 比较只取普通角色 更新缓存 需所有role
	 */
	public synchronized void saveRoleAuthorize(  FunctionVo func , String principalIds  )  throws CheckException , CacheException  {
		Long funcId = func.getFuncId ( ) ;
		List roles = new ArrayList( 1 ) ;
		List tmpRoles = new java.util.ArrayList();
		if ( principalIds != null ) {
			roles = getRolesByFunc ( func ) ;
			StringTokenizer st = new StringTokenizer( principalIds , StringPool.SEMICOLON ) ;
			int count = st.countTokens ( ) ;
			for ( int i = 0 ; i < count ; i ++  ) {
				String nt = st.nextToken ( ) ;
				//check
				boolean mark = false ;
				if ( roles.size() == 0  )  mark = true;
				for ( Iterator iter = roles.iterator ( ); iter.hasNext ( ) ;  ) {
					RoleVo role = ( RoleVo )  iter.next ( );
					Long roleId = role.getRoleId ( );
					if ( roleId .toString ( ).equals ( nt ) ) {
						iter.remove ( );
						mark = false ;
						break;
					}
					else mark = true ;
				}
				if ( mark  ) tmpRoles.add ( nt ) ;
			}
			AclVo acl = new AclVo(  );
			acl.setResourceId ( funcId ) ;
			acl.setResourceType ( Constants.RESOURCE_URL ) ;
			acl.setPrincipalType ( Constants.PRINCIPALID_ROLE ) ;
			acl.setCrtUser ( func.getCrtUser ( ) );
			//new			
				for ( Iterator iter = tmpRoles.iterator ( ); iter.hasNext ( ) ;  ) {
					Long principalId = Long.valueOf ( iter.next ( ).toString ( ) ) ;
					acl.setPrincipalId ( principalId ) ;
					OrgFactory.getAclManager ( ).doAuthorize ( acl ) ;
				}
				
				//cache
				if ( tmpRoles.size ( ) > 0 && !Constants.NULL_URL.equals ( func.getResString ( ) ) ) {
					if ( Constants.CACHE_NAME.equals ( AcegiContext.getOrgCacheKey ( ) ) ) {
						RoleVo  _role = new RoleVo( ) ; 
						Object[] objs = tmpRoles.toArray ( ) ; 
						Long[ ] roleIds = new Long[ tmpRoles.size ( ) ]  ;
						for ( int nn = 0 ; nn < objs.length ; nn ++ )  roleIds[ nn ] = Long.valueOf ( objs[ nn ].toString ( ) ) ; 
						_role.setRoleIds ( roleIds ) ;
						tmpRoles = roleDAO.getRoles ( _role ) ; 
						if ( tmpRoles.size ( ) > 0  ) {
							Object[] rolens = new Object[ tmpRoles.size ( ) ] ; 
							int i = 0 ;
							for ( Iterator iter = tmpRoles.iterator ( ); iter.hasNext ( ) ;  ) {
								RoleVo role = ( RoleVo )  iter.next ( );
								rolens[ i ] = role.getRoleName ( ) ; 
								i ++ ; 
							}		
							
							
								//since1.72
								if ( AcegiCacheManager.getInstansce ( ).getAuthorityFromCache ( func.getResString ( ) ) == null ) {
									logger.warn ( "ALLWAYS:WARN>> cache warn !"  ) ; 
									modifyInCache ( func ) ;
								}
								else 
									AcegiCacheManager.getInstansce ( )
											.modResourceAuthorityCache ( func.getResString ( ) ,
													Constants.CACHE_NEW , Constants.AUTH_TYPE_ROLE ,  rolens );								
							
						}									
					}
					else {
						
							if ( AcegiCacheManager.getInstansce ( ).getAuthorityFromCache ( func.getResString ( ) ) == null ) {
								modifyInCache ( func ) ;
								logger.warn ( "ALLWAYS:WARN>> cache warn !"  ) ;
							}
							else 						
								AcegiCacheManager.getInstansce ( )
									.modResourceAuthorityCache ( func.getResString ( ) ,
										Constants.CACHE_NEW , Constants.AUTH_TYPE_ROLE ,tmpRoles.toArray ( ) );							
						
					}

				}

		    //remove
				
				if ( roles.size ( ) > 0    ) {
					int i = 0 ; 
					Object[] rolens = new Object[ roles.size ( ) ] ; 
					for ( Iterator iter = roles.iterator ( ); iter.hasNext ( ) ;  ) {
						RoleVo role = ( RoleVo )  iter.next ( );
						if ( Constants.CACHE_NAME.equals ( AcegiContext.getOrgCacheKey ( ) ) ) 
							rolens[ i ] = role.getRoleName ( ) ; 
						else rolens[ i ] = role.getRoleId ( ) ; 
						Long principalId = role.getRoleId ( );
						acl.setPrincipalId ( principalId ) ;
						deleteFuncAuthorize ( acl , false ) ;
						i ++ ; 
					}
					
					if (  !Constants.NULL_URL.equals ( func.getResString ( ) )  ) {
						if ( AcegiCacheManager.getInstansce ( ).getAuthorityFromCache ( func.getResString ( ) ) == null ) {
							logger.warn ( "ALLWAYS:WARN>> cache warn !"  ) ;
							modifyInCache ( func ) ;
						}
						else 					
							AcegiCacheManager.getInstansce ( )
							   .modResourceAuthorityCache ( func.getResString ( ) ,
									Constants.CACHE_DEL , Constants.AUTH_TYPE_ROLE ,  rolens );						
					}
				}
			}
	}
	
	
	
	
    /**
     * TODO pagination support
     * @param functionVo
     */
	public synchronized void saveTitleAuths ( Long grpId , FunctionVo functionVo ) throws CheckException , CacheException  {
		List titlesOfGroup = groupDao.queryTitlesOfGroup ( grpId );
		List chkdTitles = functionVo.getTitles ( );
		List allAuthTitles = getTitlesByFunc ( functionVo ); // all authorized// titles

		allAuthTitles.retainAll ( titlesOfGroup );
		List authTitlesOfGroup = new ArrayList ( );
		authTitlesOfGroup.addAll ( allAuthTitles ) ;
		allAuthTitles.retainAll ( chkdTitles ) ; 
		chkdTitles.removeAll ( allAuthTitles ) ; //new 
		authTitlesOfGroup.removeAll ( allAuthTitles) ; //rm

		AclVo acl = new AclVo ( );
		acl.setResourceId ( functionVo.getFuncId ( ) );
		acl.setResourceType ( Constants.RESOURCE_URL );
		acl.setPrincipalType ( Constants.PRINCIPALID_TITLE );
		acl.setCrtUser ( functionVo.getCrtUser ( ) );
				
		// crt
		Object[] cacheTitles = new Object[ chkdTitles.size ( ) ] ; 
		for ( int i = 0 ; i < chkdTitles.size ( ) ; i ++ ) {
			TitleMsgVo titleMsgVo = ( TitleMsgVo ) chkdTitles.get ( i );
			acl.setPrincipalId ( titleMsgVo.getTitleId ( ) );
			OrgFactory.getAclManager ( ).doAuthorize ( acl );
			//cache
			cacheTitles[ i ] = titleMsgVo.getTitleId ( ) ; 
			if ( Constants.CACHE_NAME.equals ( AcegiContext.getOrgCacheKey ( ) ) ) 
				cacheTitles[ i ] = cacheTitles[ i ] + StringPool.DASH + titleMsgVo.getTitleName ( )   ; 
		
		}
		//crt cache
		if ( cacheTitles.length > 0  && !Constants.NULL_URL.equals ( functionVo.getResString ( ) )   ) {
			if ( AcegiCacheManager.getInstansce ( ).getAuthorityFromCache ( functionVo.getResString ( ) ) == null ) {
				modifyInCache ( functionVo ) ;
				logger.warn ( "ALLWAYS:WARN>> cache warn !"  ) ;
			}
			else 					
				AcegiCacheManager.getInstansce ( )
				.modResourceAuthorityCache ( functionVo.getResString ( ) ,
						Constants.CACHE_NEW , Constants.AUTH_TYPE_TITLE ,cacheTitles );			
		}
		
		// rm
		cacheTitles = new Object[ authTitlesOfGroup.size ( ) ] ; 
		for ( int i = 0 ; i < authTitlesOfGroup.size ( ) ; i ++ ) {
			TitleMsgVo titleMsgVo = ( TitleMsgVo ) authTitlesOfGroup.get ( i );
			acl.setPrincipalId ( titleMsgVo.getTitleId ( ) );
			deleteFuncAuthorize ( acl , false );
			//cache
			cacheTitles[ i ] = titleMsgVo.getTitleId ( ) ; 
			if ( Constants.CACHE_NAME.equals ( AcegiContext.getOrgCacheKey ( ) ) ) 
				cacheTitles[ i ] = cacheTitles[ i ] + StringPool.DASH + titleMsgVo.getTitleName ( )   ; 
		}
		
		//del cache
		if ( authTitlesOfGroup .size ( ) > 0 && cacheTitles.length > 0   && !Constants.NULL_URL.equals ( functionVo.getResString ( ) )   ) {
			if ( AcegiCacheManager.getInstansce ( ).getAuthorityFromCache ( functionVo.getResString ( ) ) == null ) {
				logger.warn ( "ALLWAYS:WARN>> cache warn !"  ) ;
				modifyInCache ( functionVo ) ;
			}
			else 								
				AcegiCacheManager.getInstansce ( )
					.modResourceAuthorityCache ( functionVo.getResString ( ) ,
						Constants.CACHE_DEL ,  Constants.AUTH_TYPE_TITLE , cacheTitles );
		} 
		
		//modifyInCache ( functionVo );
	}	
	
	
	public synchronized void saveRoleAuthorize( FuncComponentVo funcCompVo , String principalIds , Long operId )  throws CheckException , CacheException  {
		List roles = getRolesByFuncCompo ( funcCompVo  ) ;
		List tmpRoles = new java.util.ArrayList();
		if ( principalIds != null ) {
			StringTokenizer st = new StringTokenizer( principalIds , StringPool.SEMICOLON ) ;
			int count = st.countTokens ( ) ; 
			for ( int i = 0 ; i < count ; i ++  ) {
				String nt = st.nextToken ( ) ; 
				//check
				boolean mark = false ; 
				if ( roles.size() == 0  )  mark = true;
				for ( Iterator iter = roles.iterator ( ); iter.hasNext ( ) ;  ) {
					RoleVo role = ( RoleVo )  iter.next ( );
					Long roleId = role.getRoleId ( );
					if ( roleId .toString ( ).equals ( nt ) ) {
						iter.remove ( );
						mark = false ;
						break;
					}
					else mark = true ; 
				}
				if ( mark  ) tmpRoles.add ( nt ) ; 
			}			
			AclVo acl = new AclVo(  );
			acl.setResourceId ( funcCompVo.getFuncElementId ( ) ) ; 
			acl.setResourceType ( Constants.RESOURCE_COMPONENT ) ;
			acl.setPrincipalType ( Constants.PRINCIPALID_ROLE ) ;
			acl.setCrtUser ( operId );
	    //new 
			for ( Iterator iter = tmpRoles.iterator ( ); iter.hasNext ( ) ;  ) {
				Long principalId = Long.valueOf ( iter.next ( ).toString ( ) ) ;
				acl.setPrincipalId ( principalId ) ;
				OrgFactory.getAclManager ( ).doAuthorize (  acl ) ;						
			}
			
			//cache
			if ( tmpRoles.size ( ) > 0 ) {
				if ( Constants.CACHE_NAME.equals ( AcegiContext.getOrgCacheKey ( ) ) ) {
					RoleVo  _role = new RoleVo( ) ; 
					Object[] objs = tmpRoles.toArray ( ) ; 
					Long[ ] roleIds = new Long[ tmpRoles.size ( ) ]  ;
					for ( int nn = 0 ; nn < objs.length ; nn ++ )  roleIds[ nn ] = Long.valueOf ( objs[ nn ].toString ( ) ) ; 
					_role.setRoleIds ( roleIds ) ;
					tmpRoles = roleDAO.getRoles ( _role ) ; 
					if ( tmpRoles.size ( ) > 0  ) {
						Object[] rolens = new Object[ tmpRoles.size ( ) ] ; 
						int i = 0 ;
						for ( Iterator iter = tmpRoles.iterator ( ); iter.hasNext ( ) ;  ) {
							RoleVo role = ( RoleVo )  iter.next ( );
							rolens[ i ] = role.getRoleName ( ) ; 
							i ++ ; 
						}		
						//since1.72
						if ( AcegiCacheManager.getInstansce ( ).getAuthorityFromCache ( funcCompVo.getResString ( ) ) == null ) {
							modifyInCache ( funcCompVo ) ;
							logger.warn ( "ALLWAYS:WARN>> cache warn !"  ) ;
						}
						else 					
							AcegiCacheManager.getInstansce ( )
									.modResourceAuthorityCache ( funcCompVo.getResString ( ) ,
											Constants.CACHE_NEW , Constants.AUTH_TYPE_ROLE ,  rolens );
					}									
				}
				else {
					if ( AcegiCacheManager.getInstansce ( ).getAuthorityFromCache ( funcCompVo.getResString ( ) ) == null ) {
						modifyInCache ( funcCompVo ) ;
						logger.warn ( "ALLWAYS:WARN>> cache warn !"  ) ;
					}
					else 										
						AcegiCacheManager.getInstansce ( )
							.modResourceAuthorityCache ( funcCompVo.getResString ( ) ,
								Constants.CACHE_NEW , Constants.AUTH_TYPE_ROLE ,tmpRoles.toArray ( ) );
				}
	
			}			
	    //remove
			if ( roles.size ( ) > 0  ) {
				int i = 0 ; 
				Object[] rolens = new Object[ roles.size ( ) ] ; 			
				for ( Iterator iter = roles.iterator ( ); iter.hasNext ( ) ;  ) {
					RoleVo role = ( RoleVo )  iter.next ( );
					if ( Constants.CACHE_NAME.equals ( AcegiContext.getOrgCacheKey ( ) ) ) 
						rolens[ i ] = role.getRoleName ( ) ; 
					else rolens[ i ] = role.getRoleId ( ) ; 
					Long principalId = role.getRoleId ( );
					acl.setPrincipalId ( principalId ) ;
					deleteFuncCompAuthorize (  acl ) ; 
					i ++ ; 
				}
				if ( AcegiCacheManager.getInstansce ( ).getAuthorityFromCache ( funcCompVo.getResString ( ) ) == null ) {
					modifyInCache ( funcCompVo ) ;
					logger.warn ( "ALLWAYS:WARN>> cache warn !"  ) ;
				}
				else 									
					AcegiCacheManager.getInstansce ( )
						.modResourceAuthorityCache ( funcCompVo.getResString ( ) ,
							Constants.CACHE_DEL , Constants.AUTH_TYPE_ROLE ,  rolens );
				/*since 1.72
				if ( tmpRoles .size ( ) > 0 || roles.size ( ) > 0 ) {
					modifyInCache ( funcCompVo ) ;
				}
				*/
			}
		}		
	}
	
	
    /** mod since 1.72
     * TODO pagination support
     * @param functionVo
     */
	public synchronized void saveTitleAuths ( Long grpId , FuncComponentVo funcCompVo ) throws CheckException , CacheException  {
		List titlesOfGroup = getTitlesByFunc ( funcCompVo.getParent ( ) );
		List tOfG = groupDao.queryTitlesOfGroup ( grpId );
		titlesOfGroup.retainAll ( tOfG ) ; 
		
		List chkdTitles = funcCompVo.getTitles ( );
		List allAuthTitles = getTitlesByFuncCompId ( funcCompVo.getFuncElementId ( ) ) ;  
		allAuthTitles.retainAll ( titlesOfGroup );
		List authTitlesOfGroup = new ArrayList ( );
		authTitlesOfGroup.addAll ( allAuthTitles ) ;
		allAuthTitles.retainAll ( chkdTitles ) ; 
		chkdTitles.removeAll ( allAuthTitles ) ; //new 
		authTitlesOfGroup.removeAll ( allAuthTitles) ; //rm

		AclVo acl = new AclVo ( );
		acl.setResourceId ( funcCompVo.getFuncElementId ( ) );
		acl.setResourceType ( Constants.RESOURCE_COMPONENT );
		acl.setPrincipalType ( Constants.PRINCIPALID_TITLE );
		acl.setCrtUser ( funcCompVo.getCrtUser ( ) );
		// crt
		Object[] cacheTitles = new Object[ chkdTitles.size ( ) ] ; 
		for ( int i = 0 ; i < chkdTitles.size ( ) ; i ++ ) {
			TitleMsgVo titleMsgVo = ( TitleMsgVo ) chkdTitles.get ( i );
			acl.setPrincipalId ( titleMsgVo.getTitleId ( ) );
			OrgFactory.getAclManager ( ).doAuthorize ( acl );
			//cache
			cacheTitles[ i ] = titleMsgVo.getTitleId ( ) ; 
			if ( Constants.CACHE_NAME.equals ( AcegiContext.getOrgCacheKey ( ) ) ) 
				cacheTitles[ i ] = cacheTitles[ i ] + StringPool.DASH + titleMsgVo.getTitleName ( )   ; 
		
		}
		//crt cache
		if ( cacheTitles.length > 0 )  {
			if ( AcegiCacheManager.getInstansce ( ).getAuthorityFromCache ( funcCompVo.getResString ( ) ) == null ) {
				logger.warn ( "ALLWAYS:WARN>> cache warn !"  ) ; 
				modifyInCache ( funcCompVo ) ;
			}
			else 					
				AcegiCacheManager.getInstansce ( )
				.modResourceAuthorityCache ( funcCompVo.getResString ( ) ,
						Constants.CACHE_NEW , Constants.AUTH_TYPE_TITLE ,cacheTitles );			
		}
		
		// rm
		cacheTitles = new Object[ authTitlesOfGroup.size ( ) ] ; 
		for ( int i = 0 ; i < authTitlesOfGroup.size ( ) ; i ++ ) {
			TitleMsgVo titleMsgVo = ( TitleMsgVo ) authTitlesOfGroup.get ( i );
			acl.setPrincipalId ( titleMsgVo.getTitleId ( ) );
			deleteFuncAuthorize ( acl , false );
			//cache
			cacheTitles[ i ] = titleMsgVo.getTitleId ( ) ; 
			if ( Constants.CACHE_NAME.equals ( AcegiContext.getOrgCacheKey ( ) ) ) 
				cacheTitles[ i ] = cacheTitles[ i ] + StringPool.DASH + titleMsgVo.getTitleName ( )   ; 
		}
		
		//del cache
		if ( authTitlesOfGroup.size ( ) > 0 && cacheTitles.length > 0 ) 
			if ( AcegiCacheManager.getInstansce ( ).getAuthorityFromCache ( funcCompVo.getResString ( ) ) == null ) {
				modifyInCache ( funcCompVo ) ;
				logger.warn ( "ALLWAYS:WARN>> cache warn !"  ) ;
			}
			else 								
				AcegiCacheManager.getInstansce ( )
				.modResourceAuthorityCache ( funcCompVo.getResString ( ) ,
						Constants.CACHE_DEL ,  Constants.AUTH_TYPE_TITLE , cacheTitles );
		
		//modifyInCache ( funcCompVo );
	}		
	
	/**
	 * 删除授权 包括（岗位 ， 角色）
	 * @param vo
	 * @throws CheckException
	 */
	public synchronized void deleteFuncAuthorize( AclVo vo , boolean modifyInCache ) throws  CheckException , CacheException {
		Long funcId = vo.getResourceId ( ) ;
		Long principalId =  vo.getPrincipalId ( ) ;
		String principalType = vo.getPrincipalType ( );
		Long operUser = vo.getCrtUser ( ) ; 
		//
		OrgFactory.getAclManager ( ).deleteAcl ( vo ) ;
		/// DELETE CACHE

		FunctionVo fv = getFunc ( funcId ) ;
		if ( fv == null ) return ;
		//if ( modifyInCache ) modifyInCache( fv ) ;//since 1.72
		if ( modifyInCache   && !Constants.NULL_URL.equals ( fv.getResString ( ) )  ) {
			Object[ ] obj = new Object[ 1 ] ;
			if ( principalType == Constants.PRINCIPALID_ROLE ) {
				RoleVo tmpRole = roleDAO.getRoleById ( principalId ) ;
				if ( Constants.CACHE_NAME.equals ( AcegiContext.getOrgCacheKey ( ) ) ) 
					obj[ 0 ] = tmpRole.getRoleName ( ) ; 
				else obj[ 0 ] = tmpRole.getRoleId ( ) ;
				//cache
				if ( AcegiCacheManager.getInstansce ( ).getAuthorityFromCache ( fv.getResString ( ) ) == null ) {
					modifyInCache ( fv ) ;
					logger.warn ( "ALLWAYS:WARN>> cache warn !"  ) ;
				}
				else 									
					AcegiCacheManager.getInstansce ( )
					.modResourceAuthorityCache ( fv.getResString ( ) ,
							Constants.CACHE_DEL ,  Constants.AUTH_TYPE_ROLE , obj );
									
			}
			else if ( principalType == Constants.PRINCIPALID_TITLE ) {
				TitleMsgVo tmpTitle = titleDAO.loadTitle ( principalId ) ; 
				obj[ 0 ] = tmpTitle.getTitleId ( ) ;
				if ( Constants.CACHE_NAME.equals ( AcegiContext.getOrgCacheKey ( ) ) ) 
					obj[ 0 ] = obj[ 0 ] + StringPool.DASH + tmpTitle.getTitleName ( );
				
				//cache
				if ( AcegiCacheManager.getInstansce ( ).getAuthorityFromCache ( fv.getResString ( ) ) == null ) {
					modifyInCache ( fv ) ;
					logger.warn ( "ALLWAYS:WARN>> cache warn !"  ) ;
				}
				else 									
					AcegiCacheManager.getInstansce ( )
					.modResourceAuthorityCache ( fv.getResString ( ) ,
							Constants.CACHE_DEL ,  Constants.AUTH_TYPE_TITLE , obj );				
			}
		}
	
		//delete comps auth
		AclVo acl = new AclVo();
		acl.setPrincipalType ( principalType ) ;
		acl.setPrincipalId ( principalId );
		acl.setResourceType ( Constants.RESOURCE_COMPONENT ) ;
		acl.setOperUser ( operUser ) ;
		List comps = getFuncComps ( funcId ) ;
		for ( Iterator iter = comps.iterator ( ) ; iter.hasNext ( ) ; ) {
			FuncComponentVo comp = ( FuncComponentVo ) iter.next ( )  ;
			acl.setResourceId ( comp.getFuncElementId ( ) ) ;
			deleteFuncCompAuthorize ( acl ) ;
			//cache since 1.72
			//modifyInCache( comp ) ;
		}
	}

	//GENERATE MENU

	/****************************************************************************************
	 *               菜单组件
	 */


	////funcComp

	public synchronized void updateFuncComp ( FuncComponentVo vo )  throws CheckException , CacheException {
		FuncComponentVo ofcv = functionCompDAO.getFuncComp ( vo.getFuncElementId ( ) ) ;
		functionCompDAO.updateFuncComp ( vo ) ;
		//since 1.72
		if ( AcegiCacheManager.getInstansce ( ).getAuthorityFromCache ( ofcv.getResString ( ) ) == null ) {
			AcegiCacheManager.getInstansce ( ).removeResourceFromCache (  ofcv.getResString ( ) ) ;
			modifyInCache ( ofcv ) ;
			logger.warn ( "ALLWAYS:WARN>> cache warn !"  ) ;
		}
		else 									
			AcegiCacheManager.getInstansce ( )
					.putAuthorityInCacheByByOther ( ofcv.getResString ( ) ,
							vo.getResString ( ) , true );
	}

	public synchronized void addFuncComp ( FuncComponentVo vo )  throws CheckException {
		functionCompDAO.saveFuncComp( vo ) ;
		//since 1.72
		AcegiCacheManager.getInstansce ( )
				.resourceDetailsNullAuthorityInCache ( vo.getResString ( ) ,
						Constants.RESOURCE_COMPONENT  );
		
	}

	/**
	 * 删除资源 并删除相关授权信息
	 * @param id
	 * @throws CheckException
	 */
	public synchronized void deleteFuncComp ( Long id , Long operUser ) throws CheckException , CacheException {
		FuncComponentVo fcv =  getFuncComp( id ) ;
		if ( fcv == null ) return ; 
		String resStr = fcv .getResString ( ) ;
		functionCompDAO.deleteFuncCompById( id , operUser ) ;
		// delete acl
		OrgFactory.getAclManager ( ).deleteAclByFuncElementId ( id , operUser ) ;
		//delete cache
		AcegiCacheManager.getInstansce ( ).removeResourceFromCache (  resStr ) ;
	}



	public List getFuncComps( Long funcId ) throws CheckException {
		FuncComponentVo vo = new FuncComponentVo();
		vo.setFuncId ( funcId ) ;
		return functionCompDAO.getFuncComps ( vo ) ;
	}

	public List getFunctionCompsWithCountRel( Long funcId  ) throws CheckException {   
		FuncComponentVo vo = new FuncComponentVo();
		vo.setFuncId ( funcId ) ;
		return functionCompDAO.getFunctionCompsWithCountRel ( vo ) ;
	}

	public FuncComponentVo getFuncComp( Long funcElementId ) throws CheckException {
		return functionCompDAO.getFuncComp ( funcElementId ) ;
	}


	public List getRolesByFuncCompId ( Long id )  throws CheckException {
		return functionCompDAO.getRolesByFuncCompId ( id ) ;
	}

	public List getRolesByFuncComp ( FuncComponentVo vo ,  byte page )  throws CheckException {
		if( page == CONST.PAGE ) return  functionCompDAO.getRolesByFuncComp ( vo )  ;
		return functionCompDAO.getRolesByFuncCompNPage ( vo )  ;
	}

	public Long countgetRolesByFunctionComp( FuncComponentVo vo  ) throws CheckException { 
		return functionCompDAO.countgetRolesByFunctionComp ( vo )  ;
	}
	
	public List getRolesByFuncCompo ( FuncComponentVo vo  ) throws CheckException {
		return functionCompDAO.getRolesByFuncCompo ( vo )  ;
	}
	
	public List getTitlesByFuncCompId ( Long id )  throws CheckException {
		return functionCompDAO.getTitlesByFuncCompId ( id ) ;
	}

	public int countgetTitlesByFunctionCompId( Long id  ) throws CheckException { 
		return functionCompDAO.countgetTitlesByFunctionCompId ( id ) ;
	}
		
	public List getUsersByFuncCompId ( Long id )  throws CheckException {
		return functionCompDAO.getUsersByFuncCompId ( id ) ;
	}

	public List getFuncCompsByFuncId( Long funcId  ) throws CheckException {
		FuncComponentVo vo = new FuncComponentVo();
		vo.setFuncId ( funcId ) ;
		return functionCompDAO.getFuncComps( vo ) ;
	}



	public List getFuncClsWithPrincipals( ) throws CheckException {
		List funcs = functionCompDAO.getFuncComps();
		for  ( int  i = 0 ; i <  funcs.size() ; i ++  ) {
			FuncComponentVo func = ( FuncComponentVo ) funcs.get(  i ) ;
			if ( GetterUtil.get ( func.getCode ( ) , null )  != null  ) {
				List roles = getRolesByFuncCompId ( func.getFuncElementId ( ) ) ;
				List titles = getTitlesByFuncCompId( func.getFuncElementId ( ) ) ;
				List users = getUsersByFuncCompId( func.getFuncElementId ( ) ) ;
				func.setRoles( roles ) ;
				func.setTitles( titles ) ;
				func.setUsers( users ) ;
			}
		}
		return funcs ;
	}

	public   void modifyInCache( FuncComponentVo func  ) throws CheckException , CacheException {
		Long funcEleId = func.getFuncElementId ( ) ;
		List roles = getRolesByFuncCompId ( funcEleId ) ;
		List titles = getTitlesByFuncCompId (  funcEleId ) ;
		List users = getUsersByFuncCompId (  funcEleId ) ;
		func.setRoles( roles ) ;
		func.setTitles( titles ) ;
		func.setUsers( users ) ;
		AcegiCacheManager.getInstansce ( ).modifyResourceInCache ( func ) ;
	}



	// end funccomp
	public synchronized void deleteFuncCompAuthorize ( AclVo vo  ) throws  CheckException {
		FuncComponentVo fcv = functionCompDAO.getFuncComp ( vo.getResourceId ( ) ) ;
		if ( fcv == null )  return ; 
		OrgFactory.getAclManager ( ).deleteAcl ( vo ) ;
		
		//cache
		Object[ ] obj = new Object[ 1 ] ;
		if ( vo.getPrincipalType ( ) == Constants.PRINCIPALID_ROLE ) {
			RoleVo tmpRole = roleDAO.getRoleById ( vo.getPrincipalId ( ) ) ;
			if ( Constants.CACHE_NAME.equals ( AcegiContext.getOrgCacheKey ( ) ) ) 
				obj[ 0 ] = tmpRole.getRoleName ( ) ; 
			else obj[ 0 ] = tmpRole.getRoleId ( ) ;
			
			if ( AcegiCacheManager.getInstansce ( ).getAuthorityFromCache ( fcv.getResString ( ) ) == null ) {
				modifyInCache ( fcv ) ;
				logger.warn ( "ALLWAYS:WARN>> cache warn !"  ) ;
			}
			else 
				AcegiCacheManager.getInstansce ( )
					.modResourceAuthorityCache ( fcv.getResString ( ) ,
						Constants.CACHE_DEL ,  Constants.AUTH_TYPE_ROLE , obj );
								
		}
		else if ( vo.getPrincipalType ( ) == Constants.PRINCIPALID_TITLE ) {
			TitleMsgVo tmpTitle = titleDAO.loadTitle (  vo.getPrincipalId ( ) ) ; 
			obj[ 0 ] = tmpTitle.getTitleId ( ) ;
			if ( Constants.CACHE_NAME.equals ( AcegiContext.getOrgCacheKey ( ) ) ) 
				obj[ 0 ] = obj[ 0 ] + StringPool.DASH + tmpTitle.getTitleName ( );
			
			if ( AcegiCacheManager.getInstansce ( ).getAuthorityFromCache ( fcv.getResString ( ) ) == null )
				modifyInCache ( fcv ) ; 
			else 
				AcegiCacheManager.getInstansce ( )
					.modResourceAuthorityCache ( fcv.getResString ( ) ,
						Constants.CACHE_DEL ,  Constants.AUTH_TYPE_TITLE , obj );				
		}

	}


	/*****************************************************************************************
	 *
	              生成菜单部分
	 */
	

	public List getFunctionsByUserAllPrincipals( Long userId ) throws CheckException {
		Assert.notNull ( userId ) ; 
		return functionDAO.getFunctionsByUserAllPrincipals ( userId ) ; 
	}
	
	/*
	public List getFunctionClsByUserAllPrincipals( Long userId ) throws CheckException {
		Assert.notNull ( userId ) ; 
		return functionCompDAO.getFunctionClsByUserAllPrincipals ( userId ) ; 
	}*/
	
	////generate menu
	public List getFuncsList( Long userId  )throws  CheckException {
//s 1.68
		List tmpfuncs = getFunctionsByUserAllPrincipals( userId  )  ;
		List pathArray = new ArrayList( ); 
		for( java.util.Iterator iter  = tmpfuncs.iterator ( ) ; iter.hasNext ( ) ;  ) {
			FunctionVo func = ( FunctionVo ) iter.next ( )  ;  
			String path = func.getPath ( ) ; 
			if ( path != null && path.indexOf ( StringPool.SLE ) > 0 ) {
					String[] p_ = path.split ( StringPool.SLE ) ; 
					for ( int i = 0 ; i < p_.length ; i ++ ) {
						if ( ! pathArray .contains ( p_[ i ] ) ) {
							pathArray.add ( p_[ i ]  ) ; 
						}
					}
			}
			else {
				if ( ! pathArray .contains ( path ) ) {
					pathArray.add ( path  ) ; 
				}				
			}
		}
		
		 
		if ( pathArray.size ( ) > 0 ) {
			String[] paths = new String[ pathArray.size ( ) ]   ;
			pathArray.toArray ( paths ) ;
			tmpfuncs .addAll (  loadFunctionsByIds( paths ) )  ; 
		}
		
		return tmpfuncs ; 
	}

	public void up ( FunctionVo vo , MenuUtils mu ) throws CheckException {
		Long id = vo.getFuncId ( );
		Long pId = vo.getFfuncId ( );
		if ( mu.containsId ( id ) ) return ;
		mu.addId ( id );
		if ( pId != null && pId.longValue ( ) != 0 ) {
			FunctionVo fv = null ;
			if ( mu.containsId ( pId ) ) {
				fv = mu.getFunc ( pId ) ;
				fv.getChildrens ( ).add ( vo );
				vo.setParent ( fv );
				mu.putFunc ( vo );
			}
			else {
				fv = getFunc (  pId );
				fv.getChildrens ( ).add ( vo );
				vo.setParent ( fv );
				mu.putFunc ( vo );
				if ( ! mu.containsKey ( pId ) ) up ( fv , mu );
			}
		} else mu.putFunc ( vo );
	}




	public String generateMenu( List roots ) throws CheckException {
		StringBuffer sb = new StringBuffer();
		 for ( java.util.Iterator iter = roots.iterator ( ) ; iter.hasNext();   ){
			 FunctionVo vo = ( FunctionVo ) iter.next ( ) ;
			 if ( vo.isWorkFlg ( ) ) {
				 sb.append ( "appendNode( 'null' , '" + vo.getFuncId ( ) + "' , '"	+ vo.getFuncChn ( ) + "' , '' , 'group' );" );
				 sb.append ( "\n" ) ;
				 down( vo , sb ) ;
			 }
		 }
		 return sb.toString ( );
	}

	/**
	 * for old menu
	 * @param vo
	 * @param sb
	 * @throws CheckException
	 */
	public void down( FunctionVo vo , StringBuffer sb )  throws CheckException {
		if ( vo.isWorkFlg ( ) ) {
			List childs = vo.getChildrens ( ) ;
			//sort
			for ( int i = 0 ; i < childs.size ( ) ; i ++ ) {
				FunctionVo child = ( FunctionVo )childs.get ( i ) ;
				if ( child.isWorkFlg ( ) ) {
					String img = child.getImgPath ( ) ;
					if ( img == null  ) img = "" ;
					boolean leaf = child.isLeaf ( ) ;
					if ( leaf ) 
						sb.append ( "appendLeaf( '" + child.getFfuncId ( ) + "' , '"
								+ ( FuncAction.URL_ + child.getFuncId ( ) )
								+ "' , '" + child.getFuncChn ( ) + "' , '" + img + "' );" );
					else 
						sb.append ( "appendNode( '" + child.getFfuncId ( )
								+ "' , '" + child.getFuncId ( ) + "' , '" + child.getFuncChn ( )
								+ "' ,  '" + img + "' , 'group' );" );
					sb.append ( "\n" ) ;
					down( child  ,  sb ) ;
				}
			}
		}
	}

	public void appendBeginRootDHTMLTree( StringBuffer sb ) throws CheckException { 
		sb.append ( "<?xml version=\"1.0\"?>" ) ;
		sb.append ( "<menu>"  ) ; 
	}
	
	public void appendEndRootDHTMLTree( StringBuffer sb ) throws CheckException { 
		sb.append ( "</menu>"  ) ; 
	}
	
	public void appendDHTMLTree( FunctionVo vo , StringBuffer sb )  throws CheckException {
		if ( !vo.isWorkFlg ( ) ) return ;
		sb.append ( "<item id=\"" + vo.getFuncId ( ) +  "\" " +
				" text=\"" + XMLUtils.writeEscapedXml ( vo.getFuncChn ( ).toCharArray ( )  ) + "\"" );
		if ( vo.getImgPath ( ) != null  ) sb.append ( " img=\"" + XMLUtils.writeEscapedXml( vo.getImgPath ( ).toCharArray ( ) ) + "\"" ) ;
		sb.append ( ">" ) ;
		appendDownDHTMLTree( vo  ,  sb ) ;
		sb.append ( "</item>" ) ;
		sb.append ( "<item id=\"ms" + vo.getFuncId ( ) + "\" type=\"separator\"/>" ) ;					
		
	}

	private void appendDownDHTMLTree( FunctionVo vo , StringBuffer sb )  throws CheckException {
		if ( vo.isWorkFlg ( ) ) {
			List childs = vo.getChildrens ( ) ;
			//sort
			for ( java.util.Iterator iter = childs.iterator ( ) ; iter.hasNext ( ) ;  ) {
				FunctionVo child = ( FunctionVo ) iter.next ( ) ;
				if ( child.isWorkFlg ( ) ) {
					sb.append ( "<item id=\"" + child.getFuncId ( ) +  "\" " +
							" text=\"" + XMLUtils.writeEscapedXml( child.getFuncChn ( ).toCharArray ( ) )  + "\"" );
					if ( child.getImgPath ( ) != null  ) sb.append ( " img=\"" + XMLUtils.writeEscapedXml( child.getImgPath ( ).toCharArray ( ) )  + "\"" ) ;
					sb.append ( ">" ) ;
					appendDownDHTMLTree( child  ,  sb ) ;
					sb.append ( "</item>" ) ;
					sb.append ( "<item id=\"ms" + child.getFuncId ( ) + "\" type=\"separator\"/>" ) ;					
				}
			}
		}
	}	


	/***********************************************************************************************
	 * 菜单附加信息
	 */

	public List getFuncAttachsByFuncId( Long funcId  ) throws CheckException {
		return functionAttachDAO.getFuncAttachsByFuncId ( funcId ) ;
	}

	public FunctionAttachVo getFuncAttach( Long id )  throws CheckException {
		return functionAttachDAO.getFuncAttachById ( id ) ;
	}

	public void updateFuncAttach( FunctionAttachVo fav ) throws CheckException , CacheException {
		functionAttachDAO.updateFuncAttach ( fav ) ;
	}

	public synchronized void addFuncAttach( FunctionAttachVo fav ) throws CheckException  , CacheException {
		Long funcId = fav.getFuncId ( ) ;
		if ( funcId == null  ) return ;
		if ( fav.getId ( ) != null  &&  fav.getId ( ).longValue ( ) != 0  ) {
			fav.setUpdtUser ( fav.getCrtUser ( ) ) ;
			functionAttachDAO.updateFuncAttach( fav ) ;
		}
		else functionAttachDAO.saveFuncAttach (  fav ) ;
		//
		StringBuffer sb = new StringBuffer();
		FunctionVo func = functionDAO.getFunc ( funcId ) ; if ( func == null || !func.isLeaf ( ) ) return ;
		String ssu = func.getSecureUrl ( ) ;
		sb.append ( func.getUrl ( ) ) .append ( StringPool.SEMICOLON ) ;
		List fas = functionAttachDAO.getFuncAttachsByFuncId ( funcId ) ;
		for ( java.util.Iterator iter = fas.iterator ( ) ; iter.hasNext ( ) ;  ) {
			FunctionAttachVo fa = ( FunctionAttachVo )  iter.next ( ) ;
			sb.append ( fa.getSecureUrl ( ) ).append ( StringPool.SEMICOLON );
		}
		String tmp = sb.toString ( ) ;
		if ( sb.indexOf ( StringPool.SEMICOLON ) > 0 ) 
			 tmp = sb.substring ( 0  , sb.length ( ) -1 ) ;
		func.setSecureUrl ( tmp ) ;
		//
		functionDAO.updateFunc ( func ) ;
		//since 1.72
		if ( AcegiCacheManager.getInstansce ( ).getAuthorityFromCache ( ssu ) == null ) {
			AcegiCacheManager.getInstansce ( ).removeResourceFromCache ( ssu ) ; 
			modifyInCache ( func ) ; 
			logger.warn ( "ALLWAYS:WARN>> cache warn !"  ) ;
		}
		else 
			AcegiCacheManager.getInstansce ( )
					.putAuthorityInCacheByByOther ( ssu , tmp , true );
	}


	public synchronized void deleteFuncAttachById( Long funcId ,  Long id  , Long operUser )  throws CheckException  , CacheException{
		functionAttachDAO.deleteFuncAttachById ( id , operUser ) ;

		StringBuffer sb = new StringBuffer();
		FunctionVo func = functionDAO.getFunc ( funcId ) ;
		if ( func == null ) return ; 
		String ssu = func.getSecureUrl ( ) ;
		sb.append ( func.getUrl ( ) ) .append ( StringPool.SEMICOLON ) ;
		List fas = functionAttachDAO.getFuncAttachsByFuncId ( funcId ) ;
		for ( java.util.Iterator iter = fas.iterator ( ) ; iter.hasNext ( ) ;  ) {
			FunctionAttachVo fa = ( FunctionAttachVo )  iter.next ( ) ;
			sb.append ( fa.getSecureUrl ( ) ).append ( StringPool.SEMICOLON );
		}
		

		String tmp = sb.toString ( ) ;
		if ( sb.indexOf ( StringPool.SEMICOLON ) > 0 ) tmp = sb.substring ( 0  , sb.length ( ) -1 ) ;
		func.setSecureUrl ( tmp ) ;
		functionDAO.updateFunc ( func ) ;
		
		//since 1.72
		if ( AcegiCacheManager.getInstansce ( ).getAuthorityFromCache ( ssu ) == null ) {
			modifyInCache ( func ) ;
			AcegiCacheManager.getInstansce ( ).removeResourceFromCache ( ssu ) ;
			logger.warn ( "ALLWAYS:WARN>> cache warn !"  ) ;
		} 
		else 
			AcegiCacheManager.getInstansce ( )
				.putAuthorityInCacheByByOther ( ssu , tmp , true );
	}

	public void deleteFuncAttachsByFuncId( Long funcId , Long operUser ) throws CheckException , CacheException {
		functionAttachDAO.deleteFuncAttachsByFuncId ( funcId , operUser ) ;
	}
	
	public int countFunctions( String funcUrl ) throws CheckException {
		FunctionVo func = new FunctionVo(); 
		func.setUrl ( funcUrl ) ;
        return functionDAO.countFuncs( func );
    }
	
	public Long getcountFuns( FunctionVo func ) throws CheckException {
		return functionDAO.getcountFuns(func);
	}

	public int countFuncComps( Long funcId ) throws CheckException { 
		FuncComponentVo fc = new FuncComponentVo ( ) ; 
		fc.setFuncId ( funcId ) ; 
		return countFuncComps( fc ) ;
	}
	
	public int countFuncComps( FuncComponentVo vo  ) throws CheckException { 
		return functionCompDAO.countFuncComps ( vo ) ; 
	}
	
	public List getFuncsByPath( String path )  throws CheckException { 
		return functionDAO.getFuncsByPath ( path ) ; 
	}
	
	public FunctionVo getFuncByPath( String path ) throws CheckException {
		return functionDAO.getFuncByPath ( path ) ; 
	}	
	
	public List getRolesByFuncId4f( FuncRoleRelVo funcRoleRel ) throws CheckException {
		return functionDAO.getRolesByFuncId4f ( funcRoleRel ) ; 
	}
	
	public Long countgetRolesByFuncId4f( FuncRoleRelVo funcRoleRel )  throws CheckException { 
		return functionDAO.countgetRolesByFuncId4f ( funcRoleRel ) ; 
	}
	
	public List getRolesByFunc4fNp( FuncRoleRelVo funcRoleRel ) throws CheckException { 
		return functionDAO.getRolesByFunc4fNp ( funcRoleRel ) ; 
	}
	
	public List getFuncByRole4fNp( FuncRoleRelVo funcRoleRel ) throws CheckException { 
		return functionDAO.getFuncByRole4fNp ( funcRoleRel ) ;
	}
	
	public void createFuncRoleRel( FuncRoleRelVo funcRoleRel ) throws CheckException {
		functionDAO.createFuncRoleRel ( funcRoleRel ) ; 
	}
	
	public void deleteFuncRoleRel(  FuncRoleRelVo funcRoleRel ) throws CheckException { 
		functionDAO.deleteFuncRoleRel ( funcRoleRel ) ; 
	}
	
	public void createFuncRoleRel4f( Long funcId , Long operUser , String principalIds  )  throws CheckException {  
		List roles = new ArrayList( ) ; 
		List tmpRoles = new ArrayList();
		if ( principalIds != null ) {
			FuncRoleRelVo funcRoleRel = new FuncRoleRelVo() ; 					
			funcRoleRel.setFuncId ( funcId ) ;
			roles = getRolesByFunc4fNp ( funcRoleRel ) ;	
			principalIds = principalIds.trim ( ) ; 
			StringTokenizer st = new StringTokenizer( principalIds , StringPool.SEMICOLON ) ;
			int count = st.countTokens ( ) ;
			for ( int i = 0 ; i < count ; i ++  ) {
				String nt = st.nextToken ( ) ;
				//check
				boolean mark = false ;
				if ( roles.size() == 0  )  mark = true;
				for ( Iterator iter = roles.iterator ( ); iter.hasNext ( ) ;  ) {
					RoleVo role = ( RoleVo )  iter.next ( );
					Long roleId = role.getRoleId ( );
					if ( roleId .toString ( ).equals ( nt ) ) {
						iter.remove ( );
						mark = false ;
						break;
					}
					else mark = true ;
				}
				if ( mark  ) tmpRoles.add ( nt ) ;
			}	
			
			//funcRoleRel = new FuncRoleRelVo() ;
			funcRoleRel.setCrtUser ( operUser ) ; 										
				for ( Iterator iter = tmpRoles.iterator ( ); iter.hasNext ( ) ;  ) {									
					Long principalId = Long.valueOf ( iter.next ( ).toString ( ) ) ;
					funcRoleRel.setRoleId ( principalId ) ;
					//funcRoleRel.setFuncId ( funcId );
					createFuncRoleRel( funcRoleRel ) ; 
				}	

				for ( Iterator iter = roles.iterator ( ); iter.hasNext ( ) ;  ) {
					RoleVo role = ( RoleVo )  iter.next ( ); 													
					funcRoleRel.setRoleId ( role.getRoleId ( ) ) ;
					//funcRoleRel.setFuncId ( funcId );
					deleteFuncRoleRel ( funcRoleRel ) ;
				}
		}		
	}	
}